# Create your models here.

from django.db import models
from django.utils.translation import gettext_lazy as _
from django.core.exceptions import ValidationError
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType


class Menu(models.Model):
    """顶级菜单容器"""
    name = models.CharField(
        _("菜单名称"),
        max_length=50,
        unique=True,
        help_text=_("菜单系统的名称（如：主菜单、侧边栏菜单等）")
    )
    description = models.TextField(
        _("描述"),
        blank=True,
        help_text=_("菜单的简要描述")
    )
    created_at = models.DateTimeField(
        _("创建时间"),
        auto_now_add=True
    )
    updated_at = models.DateTimeField(
        _("更新时间"),
        auto_now=True
    )

    class Meta:
        verbose_name = _("菜单")
        verbose_name_plural = _("菜单")
        ordering = ['name']

    def __str__(self):
        return self.name


class MenuItem(models.Model):
    """菜单项模型"""
    # 菜单类型选项
    MENU_TYPE_CHOICES = (
        ('url', _("URL链接")),
        ('page', _("页面")),
        ('section', _("分组标题")),
        ('divider', _("分隔线")),
        ('dropdown', _("下拉菜单")),
    )

    # 目标打开方式选项
    TARGET_CHOICES = (
        ('_self', _("当前窗口")),
        ('_blank', _("新窗口")),
        ('_parent', _("父窗口")),
        ('_top', _("顶层窗口")),
    )

    menu = models.ForeignKey(
        Menu,
        on_delete=models.CASCADE,
        related_name='items',
        verbose_name=_("所属菜单"),
        help_text=_("该菜单项所属的菜单系统")
    )
    title = models.CharField(
        _("显示标题"),
        max_length=100,
        help_text=_("菜单项显示的文字")
    )
    type = models.CharField(
        _("菜单类型"),
        max_length=20,
        choices=MENU_TYPE_CHOICES,
        default='url',
        help_text=_("菜单项的类型")
    )
    url = models.CharField(
        _("链接地址"),
        max_length=255,
        blank=True,
        null=True,
        help_text=_("URL路径或命名路由（如：'/about/' 或 'admin:index'）")
    )
    icon = models.CharField(
        _("图标"),
        max_length=50,
        blank=True,
        null=True,
        help_text=_("图标类名（如：'fa fa-home'）")
    )
    order = models.PositiveIntegerField(
        _("排序序号"),
        default=0,
        help_text=_("菜单项在菜单中的显示顺序")
    )
    parent = models.ForeignKey(
        'self',
        on_delete=models.CASCADE,
        related_name='children',
        blank=True,
        null=True,
        verbose_name=_("父菜单项"),
        help_text=_("上级菜单项（用于创建多级菜单）")
    )
    is_active = models.BooleanField(
        _("是否激活"),
        default=True,
        help_text=_("是否在菜单中显示此项")
    )
    target = models.CharField(
        _("打开方式"),
        max_length=20,
        choices=TARGET_CHOICES,
        default='_self',
        help_text=_("链接的打开方式")
    )
    requires_login = models.BooleanField(
        _("需要登录"),
        default=False,
        help_text=_("是否要求用户登录才能看到此菜单项")
    )
    requires_group = models.ManyToManyField(
        Group,
        blank=True,
        verbose_name=_("所需用户组"),
        help_text=_("用户必须属于这些组之一才能看到此菜单项")
    )
    requires_permission = models.ManyToManyField(
        Permission,
        blank=True,
        verbose_name=_("所需权限"),
        help_text=_("用户必须拥有这些权限之一才能看到此菜单项")
    )
    css_classes = models.CharField(
        _("CSS类"),
        max_length=200,
        blank=True,
        null=True,
        help_text=_("额外的CSS类（多个类用空格分隔）")
    )
    created_at = models.DateTimeField(
        _("创建时间"),
        auto_now_add=True
    )
    updated_at = models.DateTimeField(
        _("更新时间"),
        auto_now=True
    )

    class Meta:
        verbose_name = _("菜单项")
        verbose_name_plural = _("菜单项")
        ordering = ['menu', 'order', 'title']
        unique_together = [['menu', 'title']]

    def __str__(self):
        return f"{self.title} ({self.menu.name})"

    def clean(self):
        # 验证：如果是下拉菜单类型，必须有子菜单
        if self.type == 'dropdown' and not self.children.exists():
            raise ValidationError(_("下拉菜单类型必须包含子菜单项"))

        # 验证：如果是分组标题或分隔线，不能有URL
        if self.type in ['section', 'divider'] and self.url:
            raise ValidationError(_("分组标题和分隔线类型不能设置URL"))

        # 验证：如果是URL或页面类型，必须有URL
        if self.type in ['url', 'page'] and not self.url:
            raise ValidationError(_("URL和页面类型必须设置URL"))

        # 验证：不能将自己设为自己的父项
        if self.parent and self.parent == self:
            raise ValidationError(_("菜单项不能设置自己为父项"))

        # 验证：父项不能是自己的后代
        if self.parent:
            parent = self.parent
            while parent.parent:
                if parent.parent == self:
                    raise ValidationError(_("不能创建循环的菜单层级"))
                parent = parent.parent

    def get_absolute_url(self):
        """获取菜单项的实际URL（如果适用）"""
        if self.type in ['url', 'page']:
            return self.url
        return "#"

    def is_visible_for_user(self, user):
        """检查菜单项对当前用户是否可见"""
        if not self.is_active:
            return False

        if self.requires_login and not user.is_authenticated:
            return False

        # 检查用户组要求
        if self.requires_group.exists():
            user_groups = user.groups.all()
            if not user_groups:
                return False
            if not self.requires_group.filter(id__in=user_groups.values_list('id', flat=True)).exists():
                return False

        # 检查权限要求
        if self.requires_permission.exists():
            user_perms = user.get_all_permissions()
            required_perms = set(self.requires_permission.values_list('codename', flat=True))
            if not required_perms.intersection(user_perms):
                return False

        return True

    @property
    def depth(self):
        """获取菜单项的层级深度"""
        depth = 0
        parent = self.parent
        while parent is not None:
            depth += 1
            parent = parent.parent
        return depth

    @property
    def is_top_level(self):
        """是否是顶级菜单项"""
        return self.parent is None

    def get_children_for_user(self, user):
        """获取对用户可见的子菜单项"""
        return [
            child for child in self.children.filter(is_active=True).order_by('order')
            if child.is_visible_for_user(user)
        ]


# 信号处理：自动创建菜单项权限
from django.db.models.signals import post_migrate
from django.dispatch import receiver


def create_menu_permissions(sender, **kwargs):
    content_type = ContentType.objects.get_for_model(MenuItem)

    # 创建菜单项权限
    permissions = [
        ("view_menuitem", "可以查看菜单项"),
        ("change_menuitem", "可以修改菜单项"),
        ("add_menuitem", "可以添加菜单项"),
        ("delete_menuitem", "可以删除菜单项"),
        ("manage_menus", "可以管理菜单系统"),
    ]

    for codename, name in permissions:
        Permission.objects.get_or_create(
            codename=codename,
            content_type=content_type,
            defaults={'name': name}
        )


@receiver(post_migrate)
def on_post_migrate(sender, **kwargs):
    if sender.name == 'your_app_name':  # 替换为你的应用名
        create_menu_permissions(sender, **kwargs)